{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2.0.0\n"
     ]
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "print(tf.__version__)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在深度学习中，我们通常会频繁地对数据进行操作。作为动手学深度学习的基础，本节将介绍如何对内存中的数据进行操作。\n",
    "\n",
    "在tensorflow中，tensor是一个类，也是存储和变换数据的主要工具。如果你之前用过NumPy，你会发现tensor和NumPy的多维数组非常类似。然而，tensor提供GPU计算和自动求梯度等更多功能，这些使tensor更加适合深度学习。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.2.1 Create NDArray"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们先介绍NDArray的最基本功能，我们用arange函数创建一个行向量。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(12,)\n"
     ]
    }
   ],
   "source": [
    "x = tf.constant(range(12))\n",
    "\n",
    "print(x.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=0, shape=(12,), dtype=int32, numpy=array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这时返回了一个tensor实例，其中包含了从0开始的12个连续整数。\n",
    "我们可以通过shape属性来获取tensor实例的形状。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "TensorShape([12])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们也能够通过len得到tensor实例中元素（element）的总数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "12"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "下面使用reshape函数把行向量x的形状改为(3, 4)，也就是一个3行4列的矩阵，并记作X。除了形状改变之外，X中的元素保持不变。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=2, shape=(3, 4), dtype=int32, numpy=\n",
       "array([[ 0,  1,  2,  3],\n",
       "       [ 4,  5,  6,  7],\n",
       "       [ 8,  9, 10, 11]])>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X = tf.reshape(x,(3,4))\n",
    "X"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "注意X属性中的形状发生了变化。上面x.reshape((3, 4))也可写成x.reshape((-1, 4))或x.reshape((3, -1))。由于x的元素个数是已知的，这里的-1是能够通过元素个数和其他维度的大小推断出来的。\n",
    "\n",
    "接下来，我们创建一个各元素为0，形状为(2, 3, 4)的张量。实际上，之前创建的向量和矩阵都是特殊的张量。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=5, shape=(2, 3, 4), dtype=float32, numpy=\n",
       "array([[[0., 0., 0., 0.],\n",
       "        [0., 0., 0., 0.],\n",
       "        [0., 0., 0., 0.]],\n",
       "\n",
       "       [[0., 0., 0., 0.],\n",
       "        [0., 0., 0., 0.],\n",
       "        [0., 0., 0., 0.]]], dtype=float32)>"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.zeros((2,3,4))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "类似地，我们可以创建各元素为1的张量。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=8, shape=(3, 4), dtype=float32, numpy=\n",
       "array([[1., 1., 1., 1.],\n",
       "       [1., 1., 1., 1.],\n",
       "       [1., 1., 1., 1.]], dtype=float32)>"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.ones((3,4))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们也可以通过Python的列表（list）指定需要创建的tensor中每个元素的值。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=9, shape=(3, 4), dtype=int32, numpy=\n",
       "array([[2, 1, 4, 3],\n",
       "       [1, 2, 3, 4],\n",
       "       [4, 3, 2, 1]])>"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Y = tf.constant([[2,1,4,3],[1,2,3,4],[4,3,2,1]])\n",
    "Y"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "有些情况下，我们需要随机生成tensor中每个元素的值。下面我们创建一个形状为(3, 4)的tensor。它的每个元素都随机采样于均值为0、标准差为1的正态分布。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=15, shape=(3, 4), dtype=float32, numpy=\n",
       "array([[-0.06770465, -2.518872  ,  0.5077952 ,  0.6465717 ],\n",
       "       [ 0.2775639 ,  0.15904428, -0.38203633,  0.30524674],\n",
       "       [-0.16228472, -0.7232593 ,  0.11517206, -0.49598092]],\n",
       "      dtype=float32)>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.random.normal(shape=[3,4], mean=0, stddev=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.2.2 arithmetic ops"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "tensor支持大量的运算符（operator）。例如，我们可以对之前创建的两个形状为(3, 4)的tensor做按元素加法。所得结果形状不变。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=16, shape=(3, 4), dtype=int32, numpy=\n",
       "array([[ 2,  2,  6,  6],\n",
       "       [ 5,  7,  9, 11],\n",
       "       [12, 12, 12, 12]])>"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X + Y"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "按元素乘法："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=17, shape=(3, 4), dtype=int32, numpy=\n",
       "array([[ 0,  1,  8,  9],\n",
       "       [ 4, 10, 18, 28],\n",
       "       [32, 27, 20, 11]])>"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X * Y"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "按元素除法："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=20, shape=(3, 4), dtype=float64, numpy=\n",
       "array([[ 0.  ,  1.  ,  0.5 ,  1.  ],\n",
       "       [ 4.  ,  2.5 ,  2.  ,  1.75],\n",
       "       [ 2.  ,  3.  ,  5.  , 11.  ]])>"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X / Y"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "按元素做指数运算："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=22, shape=(3, 4), dtype=float32, numpy=\n",
       "array([[ 7.389056 ,  2.7182817, 54.598152 , 20.085537 ],\n",
       "       [ 2.7182817,  7.389056 , 20.085537 , 54.598152 ],\n",
       "       [54.598152 , 20.085537 ,  7.389056 ,  2.7182817]], dtype=float32)>"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Y = tf.cast(Y, tf.float32)\n",
    "tf.exp(Y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "除了按元素计算外，我们还可以使用matmul函数做矩阵乘法。下面将X与Y的转置做矩阵乘法。由于X是3行4列的矩阵，Y转置为4行3列的矩阵，因此两个矩阵相乘得到3行3列的矩阵。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=26, shape=(3, 3), dtype=int32, numpy=\n",
       "array([[ 18,  20,  10],\n",
       "       [ 58,  60,  50],\n",
       "       [ 98, 100,  90]])>"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Y = tf.cast(Y, tf.int32)\n",
    "tf.matmul(X, tf.transpose(Y))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们也可以将多个tensor连结（concatenate）。下面分别在行上（维度0，即形状中的最左边元素）和列上（维度1，即形状中左起第二个元素）连结两个矩阵。可以看到，输出的第一个tensor在维度0的长度（ 6 ）为两个输入矩阵在维度0的长度之和（ 3+3 ），而输出的第二个tensor在维度1的长度（ 8 ）为两个输入矩阵在维度1的长度之和（ 4+4 ）。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(<tf.Tensor: id=28, shape=(6, 4), dtype=int32, numpy=\n",
       " array([[ 0,  1,  2,  3],\n",
       "        [ 4,  5,  6,  7],\n",
       "        [ 8,  9, 10, 11],\n",
       "        [ 2,  1,  4,  3],\n",
       "        [ 1,  2,  3,  4],\n",
       "        [ 4,  3,  2,  1]])>,\n",
       " <tf.Tensor: id=30, shape=(3, 8), dtype=int32, numpy=\n",
       " array([[ 0,  1,  2,  3,  2,  1,  4,  3],\n",
       "        [ 4,  5,  6,  7,  1,  2,  3,  4],\n",
       "        [ 8,  9, 10, 11,  4,  3,  2,  1]])>)"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.concat([X,Y],axis = 0), tf.concat([X,Y],axis = 1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用条件判断式可以得到元素为0或1的新的tensor。以X == Y为例，如果X和Y在相同位置的条件判断为真（值相等），那么新的tensor在相同位置的值为1；反之为0。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=31, shape=(3, 4), dtype=bool, numpy=\n",
       "array([[False,  True, False,  True],\n",
       "       [False, False, False, False],\n",
       "       [False, False, False, False]])>"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.equal(X,Y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "对tensor中的所有元素求和得到只有一个元素的tensor。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=33, shape=(), dtype=int32, numpy=66>"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tf.reduce_sum(X)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=39, shape=(), dtype=float32, numpy=22.494444>"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X = tf.cast(X, tf.float32)\n",
    "tf.norm(X)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.2.3 broadcasting"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "前面我们看到如何对两个形状相同的tensor做按元素运算。当对两个形状不同的tensor按元素运算时，可能会触发广播（broadcasting）机制：先适当复制元素使这两个tensor形状相同后再按元素运算。\n",
    "\n",
    "定义两个tensor："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(<tf.Tensor: id=42, shape=(3, 1), dtype=int32, numpy=\n",
       " array([[0],\n",
       "        [1],\n",
       "        [2]])>,\n",
       " <tf.Tensor: id=45, shape=(1, 2), dtype=int32, numpy=array([[0, 1]])>)"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = tf.reshape(tf.constant(range(3)), (3,1))\n",
    "B = tf.reshape(tf.constant(range(2)), (1,2))\n",
    "A, B"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "由于A和B分别是3行1列和1行2列的矩阵，如果要计算A + B，那么A中第一列的3个元素被广播（复制）到了第二列，而B中第一行的2个元素被广播（复制）到了第二行和第三行。如此，就可以对2个3行2列的矩阵按元素相加。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=46, shape=(3, 2), dtype=int32, numpy=\n",
       "array([[0, 1],\n",
       "       [1, 2],\n",
       "       [2, 3]])>"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A + B"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.2.4 indexing"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在tensor中，索引（index）代表了元素的位置。tensor的索引从0开始逐一递增。例如，一个3行2列的矩阵的行索引分别为0、1和2，列索引分别为0和1。\n",
    "\n",
    "在下面的例子中，我们指定了tensor的行索引截取范围[1:3]。依据左闭右开指定范围的惯例，它截取了矩阵X中行索引为1和2的两行。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=50, shape=(2, 4), dtype=float32, numpy=\n",
       "array([[ 4.,  5.,  6.,  7.],\n",
       "       [ 8.,  9., 10., 11.]], dtype=float32)>"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X[1:3]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们可以指定tensor中需要访问的单个元素的位置，如矩阵中行和列的索引，并为该元素重新赋值。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Variable 'UnreadVariable' shape=(3, 4) dtype=float32, numpy=\n",
       "array([[ 0.,  1.,  2.,  3.],\n",
       "       [ 4.,  5.,  9.,  7.],\n",
       "       [ 8.,  9., 10., 11.]], dtype=float32)>"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X = tf.Variable(X)\n",
    "X[1,2].assign(9)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "当然，我们也可以截取一部分元素，并为它们重新赋值。在下面的例子中，我们为行索引为1的每一列元素重新赋值。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Variable 'Variable:0' shape=(3, 4) dtype=float32, numpy=\n",
       "array([[ 0.,  1.,  2.,  3.],\n",
       "       [ 4.,  5.,  9.,  7.],\n",
       "       [ 8.,  9., 10., 11.]], dtype=float32)>"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X = tf.Variable(X)\n",
    "X"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Variable 'UnreadVariable' shape=(3, 4) dtype=float32, numpy=\n",
       "array([[ 0.,  1.,  2.,  3.],\n",
       "       [12., 12., 12., 12.],\n",
       "       [ 8.,  9., 10., 11.]], dtype=float32)>"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X[1:2,:].assign(tf.ones(X[1:2,:].shape, dtype = tf.float32)*12)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.2.5 saving memory"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在前面的例子里我们对每个操作新开内存来存储运算结果。举个例子，即使像Y = X + Y这样的运算，我们也会新开内存，然后将Y指向新内存。为了演示这一点，我们可以使用Python自带的id函数：如果两个实例的ID一致，那么它们所对应的内存地址相同；反之则不同。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X = tf.Variable(X)\n",
    "Y = tf.cast(Y, dtype=tf.float32)\n",
    "\n",
    "before = id(Y)\n",
    "Y = Y + X\n",
    "id(Y) == before"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果想指定结果到特定内存，我们可以使用前面介绍的索引来进行替换操作。在下面的例子中，我们先通过zeros_like创建和Y形状相同且元素为0的tensor，记为Z。接下来，我们把X + Y的结果通过[:]写进Z对应的内存中。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Z = tf.Variable(tf.zeros_like(Y))\n",
    "before = id(Z)\n",
    "Z[:].assign(X + Y)\n",
    "id(Z) == before"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "实际上，上例中我们还是为X + Y开了临时内存来存储计算结果，再复制到Z对应的内存。如果想避免这个临时内存开销，我们可以使用运算符全名函数中的out参数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Z = tf.add(X, Y)\n",
    "id(Z) == before"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果X的值在之后的程序中不会复用，我们也可以用 X[:] = X + Y 或者 X += Y 来减少运算的内存开销。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "before = id(X)\n",
    "X.assign_add(Y)\n",
    "id(X) == before"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.2.6 trans between numpy"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们可以通过array函数和asnumpy函数令数据在NDArray和NumPy格式之间相互变换。下面将NumPy实例变换成tensor实例。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Tensor: id=115, shape=(2, 3), dtype=float64, numpy=\n",
       "array([[1., 1., 1.],\n",
       "       [1., 1., 1.]])>"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "P = np.ones((2,3))\n",
    "D = tf.constant(P)\n",
    "D"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "再将NDArray实例变换成NumPy实例。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 1., 1.],\n",
       "       [1., 1., 1.]])"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.array(D)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "tf2.0",
   "language": "python",
   "name": "tf2.0"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
